Problem s uvolnovanim pameti - chybove hlaseni - okno CPU
Otázka od: js-delphi@quick.cz
14. 4. 2004 4:35
Ahoj panove.
Mam dost velky problem. Aplikace, kterou jsem prevzal se chova velice
nestandardne a ja si s ni uz nevim rady.
Nektere "f-ce" (nemyslim function) se daji opakovat nekolikrat a pak zacnou
zpusobovat vyjimky. Pokud ladim kod primo v Delphi, tak mi to skace do pro me
nezvykleho okna CPU s hlasenim jako:
"Project ...\Project.exe raised too many consecutive exceptions: 'access violation at 0x0000000000 read of addres 0x0000000000'. Process Stopped. Use Step or Run to continue."
nebo
"... faulted with message: 'access violation at ...' ..."
Domnivam se tedy, ze ta aplikace a jeji knihovny spatne zachazeji s pameti -
souhlasite se mnou?
No a ted moje otazky.
(1) Stahl jsem si MemProof, ale vubec se v nem neorientuji. Nemohl byste me
nekdo navest co kde mam videt a co kdyz vidim, tak mi to rekne? (kdyz to bude
jak pro blbe, bude to nejlepsi )
(2) muzete mi nekdo vysvetlit kdy a jak se uvolnuji ktere promenne, tridy,
objekty? Je treba rucne uvolnovat vsechno? Delam chybu, kdyz vsechno co
vytvarim (napr. L:=TStrings.Create;) pak uvolnuju vzdy pres FreeAndNil? Ja jsem
si vsiml ve zdrojovych kodech Delphi, ze to neni pouzivano tak casto jak bcyh
cekal a tak nevim, jestli postupuju spravne. Musim uvolnovat i stringy? Jak?
(3) MemProof mi hlasi chyby typu "Pokus o uvolneni neexistujiciho zdroje" -
muzete mi nekdo priblizit co asi tak delam/aplikace za chybu?
Predem vsem moc diky!
Jirka
--------------------------------------------------
Ing. Jiri Sokol; jiri.sokol@seznam.cz; 972 231 187
D6Prof+SP3; WinXPProf+SP1; FB 1.0.3
programator amater
Odpovedá: Petr Daricek
14. 4. 2004 6:53
> (1) Stahl jsem si MemProof, ale vubec se v nem neorientuji. Nemohl byste me
nekdo navest co kde mam videt a co kdyz vidim, tak mi to rekne? (kdyz to bude
jak pro blbe, bude to nejlepsi )
> (2) muzete mi nekdo vysvetlit kdy a jak se uvolnuji ktere promenne, tridy,
objekty? Je treba rucne uvolnovat vsechno? Delam chybu, kdyz vsechno co
vytvarim (napr. L:=TStrings.Create;) pak uvolnuju vzdy pres FreeAndNil? Ja jsem
si vsiml ve zdrojovych kodech Delphi, ze to neni pouzivano tak casto jak bcyh
cekal a tak nevim, jestli postupuju spravne. Musim uvolnovat i stringy? Jak?
> (3) MemProof mi hlasi chyby typu "Pokus o uvolneni neexistujiciho zdroje" -
muzete mi nekdo priblizit co asi tak delam/aplikace za chybu?
>
> Predem vsem moc diky!
> Jirka
1) Koukni se na http://users.pandora.be/stefancr/Delphi%20-%20MemProof.htm
2) FreeandNil rozhodne neni chyba. Pri free se uvolni pamet, ale ukazatel stale
nekam ukazuje a tak neni poznat jestli neukazuje na platne data. Prirazenim
nilu se tohle osetri. Stringy uvolnovat nemusis. Uvolnuji se jen dynamicke
promenne a objekty(ty jsou take dynamicke). String nevytvaris pred pouzitim
pres zadny create ani new.
Petr Daricek
Odpovedá: Karel Rys
14. 4. 2004 7:14
js-delphi@quick.cz dne 14 Apr 2004 v 5:20:
> (3) MemProof mi hlasi chyby typu "Pokus o uvolneni
> neexistujiciho zdroje" -
muzete mi nekdo priblizit co asi tak
> delam/aplikace za chybu?
To je prave problem - znamena to, ze se napr. udelalo Objekt.Free a potom se
nekde znovu vola
Objekt.Free - pokousi se to uvolnit podruhe. Nebo se vola FreeMem a preda se
promenna, do ktere se
predtim pamet nealokovala...
Karel Rys
Odpovedá: js-delphi@quick.cz
14. 4. 2004 8:13
Odesilatel: Karel Rys <delphi@zas-me.cz>
> > (3) MemProof mi hlasi chyby typu
"Pokus o uvolneni
> > neexistujiciho zdroje" - muzete mi nekdo priblizit co
asi tak
> > delam/aplikace za chybu?
>
> To je prave problem - znamena to, ze se napr. udelalo Objekt.Free
> a potom se nekde znovu vola
> Objekt.Free - pokousi se to uvolnit podruhe. Nebo se vola FreeMem
> a preda se promenna, do ktere se
> predtim pamet nealokovala...
No a jak se to spravne otestuje? Kdy mam pouzit:
if Asssigned(L) then FreeAndNil(L);
a kdy
if L <> nil then FreeAndNil(L);
Je teda spravne, ze jsem temer vsude misto "L.free" nasekal FreeAndNil(L). Pak
mi neni jasne, proc to zlobi cim dal vic...
Jeste jeden dotaz:
Jak spravne uvolnim takovouhle pamet?
procedure Neco;
var
L:TStringList;
begin
...
L:=Funkce01;
end;
function Funkce01;
begin
result:=TStringList.Create;
result.add('a');
result.add('b');
result.add('c');
end;
Z niceho nic mi aplikace zacala padat na jakykoliv pokus o uvolneni pameti -
vsechno konci s chybou (FreeAndNil(L), L.Free) JAK TO??? Testoval jsem to pred
tim uvolnenim:
if L <> nil then FreeAndNil(L);
ale to stejne konci vyjimkou...
Diky za Vase rady. Ocenim jakekoliv Vase zkusenosti - zkuste mi napsat jake
jste delali chyby ve svych zacatcich - treba se jich taky dopoustim a jeste to
ani neumim spravne popsat!
Jirka
--------------------------------------------------
Ing. Jiri Sokol; jiri.sokol@seznam.cz; 972 231 187
D6Prof+SP3; WinXPProf+SP1; FB 1.0.3
programator amater
Odpovedá: Karel Rys
14. 4. 2004 8:50
js-delphi@quick.cz dne 14 Apr 2004 v 9:02:
> No a jak se to spravne otestuje? Kdy mam pouzit:
> if Asssigned(L) then FreeAndNil(L);
> a kdy
> if L <> nil then FreeAndNil(L);
> Je teda spravne, ze jsem temer vsude misto "L.free" nasekal
> FreeAndNil(L). Pak mi neni jasne, proc to zlobi cim dal vic...
Rekl bych, ze FreeAndNil si to testuje samo - pokud je predavany objekt nil,
neudela nic; pokud
neni nil, uvolni ho volanim objekt.Free a nastavi ho na nil (takze se pri
pristim volani
FreeAndNil uz nestane nic).
> Jeste jeden dotaz:
> Jak spravne uvolnim takovouhle pamet?
> procedure Neco;
> var
> L:TStringList;
> begin
> ...
> L:=Funkce01;
> end;
>
> function Funkce01;
> begin
> result:=TStringList.Create;
> result.add('a');
> result.add('b');
> result.add('c');
> end;
Spis bych zvazil, zda pouzivat takovyhle zpusob vytvareni objektu. Napsal bych
to radeji nejak
takto:
procedure Neco;
var
L:TStringList;
begin
L:=tStringList.Create;
try
Fuknce01(L);
...
finally
FreeAndNil(L); // nebo L.Free;
end;
end;
procedure Funkce01(Cil:tStringList);
begin
Cil.add('a');
Cil.add('b');
Cil.add('c');
end;
> Diky za Vase rady. Ocenim jakekoliv Vase zkusenosti - zkuste mi napsat
> jake jste delali chyby ve svych zacatcich - treba se jich taky
> dopoustim a jeste to ani neumim spravne popsat!
Rekl bych, ze chybam se da slusne predchazet v pripade, ze alokaci i uvolneni
muzes dat do jedne
casti kodu, tj. klasicke:
L:=tNeco.Create;
try
.....
finally
L.Free; // nebo FreeAndNil
end;
Karel Rys
Odpovedá: Petr Fejfar
14. 4. 2004 9:13
js-delphi@quick.cz wrote:
> Diky za Vase rady. Ocenim jakekoliv Vase zkusenosti - zkuste mi
> napsat jake jste delali chyby ve svych zacatcich - treba se jich taky
> dopoustim a jeste to ani neumim spravne popsat!
Za meho mladi jsme takove chyby proste nedelali,
protoze nez nas nekdo pustil k pocitaci, tak jsme
museli nastudovat radu script a manualu
- byli jsme tudiz teoreticky slusne pripraveni <g>
Vazne - chce to teoretickou prupravu - pokud si nebudes
na Tebou kladene otazky schopen odpovedet sam,
tak se IMHO s tim memory managementem nikdy
nevyporadas a vysledkem bude jen nejaky vice ci mene
nahodily slepenec a ne aplikace, nad kterou mas kontrolu.
Alespon si precti v helpu kapitoly
- Object Pascal Reference | Memory management
- Object Pascal Reference | Program control
a taky si projdi popis metod basalni tridy TObject - doporucuji spojit
s nahlizenim do zdrojovek RTL dodavanych s Delphi.
HTH, pf
Odpovedá: jsdelphi@creatix.cz
14. 4. 2004 11:39
>Jak spravne uvolnim takovouhle pamet?
>procedure Neco;
>var
>L:TStringList;
>begin
> ...
> L:=Funkce01;
>end;
>function Funkce01;
>begin
> result:=TStringList.Create;
> result.add('a');
> result.add('b');
> result.add('c');
>end;
Ja bych pouzil konstrukci:
procedure Neco;
var
L: TStringList;
begin
...
L := Funkce01;
try
...
finally
FreeAndNil(L);
end;
end;
function Funkce01;
begin
result := TStringList.Create;
result.add('a');
result.add('b');
result.add('c');
end;
Jan Skopovy
Odpovedá: Petr Vones
14. 4. 2004 12:20
From: <js-delphi@quick.cz>
> Je teda spravne, ze jsem temer vsude misto "L.free" nasekal FreeAndNil(L).
Neni. Je treba nejdrive pochopit jak vubec sprava pameti funguje. Pak nebudes
(ve vetsine pripadu delat chyby ktere povedou k takovym problemum. Anebo
prejdi na .NET kde tyto problemy z principu neexistuji, ale zase jsou tam
jine.
> function Funkce01;
> begin
> result:=TStringList.Create;
> result.add('a');
> result.add('b');
> result.add('c');
> end;
Jestlize funkce vraci jako result nejaky objekt tak by to melo obecne vypadat
spise takto, protoze v pripade ze dojde k vyjimce pri volani nekterych metod
toho objektu je nutne objekt v dane funkci explicitne uvolnit pred vyvolanim
vyjimky:
function Funkce01: TStringList;
begin
Result := TStringList.Create;
try
// zde muze dojit k nejake vyjimce
Result.Add('a');
Result.Add('b');
Result.Add('c');
except
Result.Free;
raise;
end;
end;
Samozrejme zalezi na navrhu, objekt se muze v konstruktoru sam pridat do
nejakeho seznamu ktery jej pozdeji uvolni apod. Jako dalsi reseni se nabizi
pouzit interface, pak se o uvolnovani nemusis starat, ale ma to zase jine
nevyhody.
Petr Vones
Odpovedá: Martin Schayna
14. 4. 2004 15:33
Petr Fejfar <development@callnet.cz> wrote:
> js-delphi@quick.cz wrote:
>> Diky za Vase rady. Ocenim jakekoliv Vase zkusenosti - zkuste mi
>> napsat jake jste delali chyby ve svych zacatcich - treba se jich taky
>> dopoustim a jeste to ani neumim spravne popsat!
>
> Za meho mladi jsme takove chyby proste nedelali,
> protoze nez nas nekdo pustil k pocitaci, tak jsme
> museli nastudovat radu script a manualu
> - byli jsme tudiz teoreticky slusne pripraveni <g>
<G>. Mas naprostou pravdu. I kdyz tenkrat jsme se
to ucili s "opravdovymi" pointery a rucnim alokovanim
pameti GetMem/FreeMem resp. New/Dispose, coz
je zaklad o ktery je mozno se oprit pri hledani problemu
s alokaci i v dobe "opravdovych" objektu.
Ovsem co si budeme povidat, takova garbage collection
je pro programatora pozehnani...
Martin Schayna